﻿using System.Collections;
using System.Diagnostics.CodeAnalysis;

namespace DimensionsHelper.LanguageService.Syntax;

public class MetadataCategories : MetadataOrder, IReadOnlyList<MetadataCategory>
{
    private SyntaxList<MetadataCategory>? _elements;


    private SyntaxToken? _leftCurlyToken;
    private SyntaxToken? _rightCurlyToken;

    internal MetadataCategories(SyntaxNode? parent) :
        base(SyntaxKinds.MetadataCategories, parent)
    {
    }

    public static MetadataCategories Default { get; } = new(null);


    public SyntaxToken? LeftCurlyToken => _leftCurlyToken;


    public SyntaxToken? RightCurlyToken => _rightCurlyToken;


    public int Count => _elements?.Count ?? 0;


    public MetadataCategory this[int index]
    {
        get
        {
            if (_elements == null)
            {
                throw new IndexOutOfRangeException(nameof(index));
            }

            return _elements[index];
        }
    }


    public IEnumerator<MetadataCategory> GetEnumerator()
    {
        return _elements?.GetEnumerator() ?? Enumerable.Empty<MetadataCategory>().GetEnumerator();
    }

    IEnumerator IEnumerable.GetEnumerator()
    {
        return GetEnumerator();
    }


    public static bool IsDefault([NotNullWhen(false)] MetadataCategories? categories)
    {
        return categories == null || ReferenceEquals(categories, Default);
    }


    public void Add(MetadataCategory category)
    {
        AddChildMember(ref _elements, category);
    }


    public MetadataCategories Update(SyntaxToken leftCurlyToken, SyntaxToken rightCurlyToken)
    {
        SetChildNullableField(ref _leftCurlyToken, SyntaxToken.IsNullOrEmpty, leftCurlyToken);
        SetChildNullableField(ref _rightCurlyToken, SyntaxToken.IsNullOrEmpty, rightCurlyToken);
        return this;
    }


    public override void AcceptVisitor<T>(SyntaxNodeVisitor<T> visitor)
    {
        Accept(visitor, LeftCurlyToken, RightCurlyToken);
        base.AcceptVisitor(visitor);
    }
}


public static partial class NodeFactory
{
    public static MetadataCategories CreateMetadataCategories(SyntaxNode? parent,
        IEnumerable<MetadataCategory>? categories)
    {
        MetadataCategories list = new(parent);

        if (categories != null)
        {
            foreach (MetadataCategory category in categories)
            {
                list.Add(category);
            }
        }

        return list;
    }
}